/**
 *
 */
package cn.hg.jfsa.manage.interceptor;

import java.util.Date;
import java.util.Enumeration;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;

import cn.hg.base.common.BaseConstants;
import cn.hg.base.jfinal.controller.BaseController;
import cn.hg.base.kit.RequestKit;
import cn.hg.jfsa.common.JfsaLogManager;
import cn.hg.jfsa.core.JfsaThreadLocal;
import cn.hg.jfsa.model.JfsaAdmin;
import cn.hg.jfsa.model.JfsaLogAction;
import cn.hg.jfsa.model.JfsaResource;
import eu.bitwalker.useragentutils.Browser;
import eu.bitwalker.useragentutils.OperatingSystem;
import eu.bitwalker.useragentutils.UserAgent;

/**
 * @author golly
 */
public class AuthInterceptor implements Interceptor {

	private static int maxOutputLengthOfParaValue = 1020;

	/*
	 * (non-Javadoc)
	 * @see com.jfinal.aop.Interceptor#intercept(com.jfinal.aop.Invocation)
	 */
	@Override
	public void intercept (Invocation inv) {
		JfsaAdmin admin = JfsaThreadLocal.getAdmin();
		inv.getController().setAttr(BaseConstants.CURRENT_ADMIN, admin);
		Map<String, JfsaResource> actionMap = JfsaThreadLocal.getAdminAuthAction();
		JfsaResource resource = actionMap.get(inv.getActionKey());
		Date now = new Date();

		if (null != admin && admin.getId() == 1 || null != actionMap && actionMap.containsKey(inv.getActionKey())) { // ID为1的超级用户具有所有权限
			// 设置当前登录的admin实例到页面
			inv.invoke();
			// 处理操作日志
			this.getLog(admin, inv, resource, now);
		} else {

			if (inv.getController() instanceof BaseController) {
				BaseController c = (BaseController) inv.getController();

				if (c.isAjaxRequest()) { // 如果是Ajax请求
					c.renderAjaxFailed("-1", "您没有此操作的权限，请联系管理员！");
				} else {
					c.render("/manage/no_right.html");
				}

			}

		}

	}

	/**
	 * 获取用户浏览器、操作系统等信息
	 *
	 * @param request
	 *            HttpServletRequest实例
	 * @param logAction
	 *            日志模型
	 */
	private void getAgentInfo (HttpServletRequest request, JfsaLogAction logAction) {
		// 解析agent字符串
		UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
		// 获取浏览器对象
		Browser browser = userAgent.getBrowser();
		// 获取操作系统对象
		OperatingSystem operatingSystem = userAgent.getOperatingSystem();
		logAction.setBrowser(browser.getName());
		logAction.setBrowserType(browser.getBrowserType().getName());
		logAction.setBrowserGroup(browser.getGroup().getName());
		logAction.setBrowserManufacturer(browser.getManufacturer().getName());
		logAction.setBrowserRenderingEngine(browser.getRenderingEngine().toString());
		logAction.setBrowserVersion(userAgent.getBrowserVersion().getVersion());
		logAction.setOs(operatingSystem.getName());
		logAction.setOsDeviceType(operatingSystem.getDeviceType().getName());
		logAction.setOsGroup(operatingSystem.getGroup().getName());
		logAction.setOsManufacturer(operatingSystem.getManufacturer().name());
		userAgent = null;
		browser = null;
		operatingSystem = null;
	}

	private void getLog (JfsaAdmin admin, Invocation inv, JfsaResource resource, Date accessTime) {

		// 操作是否允许记录日志
		if (resource == null || !resource.getIsLog()) {
			return;
		}

		// 日志是否打开
		if (!JfsaLogManager.me().isLogEnabled()) {
			return;
		}

		HttpServletRequest request = inv.getController().getRequest();
		// 获取refer URL
		String url = request.getRequestURL().toString();
		String refer = RequestKit.getReferer(request);

		if (url.equals(refer)) {
			refer = null;
		}

		JfsaLogAction log = new JfsaLogAction()
			.setActionName(resource == null ? null : resource.getName())
			.setActionTime(accessTime)
			.setAdminId(admin.getId())
			.setClientIp(RequestKit.getIpAddress(request))
			.setCookieId(inv.getController().getCookieObjects().toString())
			.setExecutionTime((int) (new Date().getTime() - accessTime.getTime()))
			.setParams(this.getParaString(request))
			.setQueryString(request.getQueryString())
			.setRefer(refer)
			.setSessionId(inv.getController().getCookie("JSESSIONID"))
			.setServerIp(request.getLocalAddr())
			.setUri(request.getRequestURI());
		// 获取用户浏览器、操作系统信息
		this.getAgentInfo(request, log);
		JfsaLogManager.me().add(log);
	}

	private String getParaString (HttpServletRequest request) {
		StringBuilder sb = new StringBuilder();
		// print all parameters
		Enumeration<String> e = request.getParameterNames();

		if (e.hasMoreElements()) {

			while (e.hasMoreElements()) {
				String name = e.nextElement();
				String[] values = request.getParameterValues(name);

				if (values.length == 1) {
					sb.append(name).append("=");

					if (values[0] != null && values[0].length() > AuthInterceptor.maxOutputLengthOfParaValue) {
						sb.append(values[0].substring(0, AuthInterceptor.maxOutputLengthOfParaValue)).append("...");
					} else {
						sb.append(values[0]);
					}

				} else {
					sb.append(name).append("[]={");

					for (int i = 0; i < values.length; i++) {

						if (i > 0) {
							sb.append(",");
						}

						sb.append(values[i]);
					}

					sb.append("}");
				}

				sb.append("  ");
			}

		}

		return sb.toString();
	}

}
